home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / so91.lha / Scan / DirComp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-23  |  12.7 KB  |  426 lines

  1. ;/* DirComp.c - AmigaMail Directory Compare example using MatchFirst()/Next().
  2. lc -cfis -v -d0 -b0 -j73 DirComp.c
  3. blink from DirComp.o to DirComp lib lib:amiga.lib ; if you don't have pragmas
  4. quit
  5.  *
  6.  * Pure code if pragmas are used.
  7.  * Monday, 15-Jul-91 16:07:31, Ewout
  8.  *
  9.  * Compiled with SAS/C 5.10a
  10.  */
  11. /* (c)  Copyright 1991 Commodore-Amiga, Inc.   All rights reserved.
  12. The information contained herein is subject to change without notice,
  13. and is provided "as is" without warranty of any kind, either expressed
  14. or implied.  The entire risk as to the use of this information is
  15. assumed by the user.
  16. */
  17.  
  18. #include <exec/memory.h>
  19. #include <dos/dosextens.h>
  20. #include <dos/rdargs.h>
  21.  
  22. #include <clib/exec_protos.h>
  23. #include <clib/dos_protos.h>
  24.  
  25. /* undef PRAGMAS if you don't have them */
  26. #undef PRAGMAS
  27. #ifdef PRAGMAS
  28. #include <pragmas/exec_pragmas.h>
  29. #include <pragmas/dos_pragmas.h>
  30. #else
  31. struct ExecBase *SysBase;
  32. struct DosLibrary *DOSBase;
  33.  
  34. #endif
  35.  
  36. /* Default size of buffer to build full targetpaths in */
  37. #define BUFFERSIZE 256
  38.  
  39. static UBYTE   *VersTag = "\0$VER: DirComp 37.1 (15.07.91)";
  40.  
  41. LONG            main(VOID);
  42. LONG            GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize);
  43. UBYTE          *ItsWild(UBYTE * string);
  44. UWORD           StrLen(UBYTE *);
  45.  
  46. LONG
  47. main(VOID)
  48. {
  49. #ifdef PRAGMAS
  50.   struct DosLibrary *DOSBase;
  51.  
  52. #endif
  53.   struct RDArgs  *readargs;
  54.   LONG            rargs[5], vargs[5];
  55.   UBYTE          *source, *target;
  56.   ULONG           buffersize = 0;
  57.   UBYTE          *sourcedir, *targetdir;
  58.   UBYTE          *textbuffer, *tmp, *tmp1, *tmp2;
  59.   struct AnchorPath *anchorpath;
  60.   struct FileInfoBlock *fib, *targetfib;
  61.   struct Process *process;
  62.   APTR            wptr;
  63.   BPTR            dirlock, filelock;
  64.   BOOL            checkdatestamp, all;
  65.   LONG            date, error, rc = 0;
  66.  
  67. #ifndef PRAGMAS
  68.   /* set up SysBase */
  69.   SysBase = (*((struct Library **) 4));
  70. #endif
  71.  
  72.   /* Fail silently if < 37 */
  73.   if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
  74.   {
  75.     rargs[0] = 0L;
  76.     rargs[1] = 0L;
  77.     rargs[2] = 0L;
  78.     rargs[3] = 0L;
  79.     rargs[4] = 0L;
  80.  
  81.     if (readargs = ReadArgs("SOURCE/A,TARGET/A,DATE/S,ALL/S,BUFFER/K/N", rargs, NULL))
  82.     {
  83.  
  84.       source = (UBYTE *) rargs[0];
  85.       target = (UBYTE *) rargs[1];
  86.       checkdatestamp = (BOOL) rargs[2];
  87.       all = (BOOL) rargs[3];
  88.  
  89.       if (!(sourcedir = AllocMem(StrLen(source) + 129, MEMF_CLEAR)))
  90.         error = ERROR_NO_FREE_STORE;
  91.       else
  92.       {
  93.         /* 128 bytes to print informative text */
  94.         textbuffer = sourcedir + StrLen(source) + 1;
  95.  
  96.         /* use user specified buffersize if indicated */
  97.         if (rargs[4])
  98.           buffersize = *((LONG *) rargs[4]);
  99.         if (buffersize < BUFFERSIZE || buffersize > 4096)
  100.           buffersize = BUFFERSIZE;
  101.  
  102.         if (!(targetdir = AllocMem(buffersize, MEMF_CLEAR)))
  103.           error = ERROR_NO_FREE_STORE;
  104.         else
  105.         {
  106.           if (!(targetfib = AllocDosObject(DOS_FIB, NULL)))
  107.             error = ERROR_NO_FREE_STORE;
  108.           else
  109.           {
  110.  
  111.             /*
  112.              * Check if source and target are valid.
  113.              *
  114.              * Separate source path from pattern (if any). Use the source path figure
  115.              * out what to append to the target.
  116.              */
  117.  
  118.             /* No requesters */
  119.             process = (struct Process *) FindTask(NULL);
  120.             wptr = process->pr_WindowPtr;
  121.             process->pr_WindowPtr = (APTR) - 1L;
  122.  
  123.             if ((error = GetPath(source, sourcedir, StrLen(source) + 1) == 0))
  124.             {
  125.               if (!(dirlock = Lock(sourcedir, SHARED_LOCK)))
  126.                 error = IoErr();
  127.               else
  128.               {
  129.                 UnLock(dirlock);
  130.                 if (!(dirlock = Lock(target, SHARED_LOCK)))
  131.                   error = IoErr();
  132.                 else
  133.                 {
  134.                   UnLock(dirlock);
  135.  
  136.                   if (anchorpath = AllocMem(sizeof(struct AnchorPath) + buffersize,
  137.                                             MEMF_CLEAR))
  138.                   {
  139.                     anchorpath->ap_Strlen = buffersize;
  140.  
  141.                     /* Allow to break on CTRL-C */
  142.                     anchorpath->ap_BreakBits = SIGBREAKF_CTRL_C;
  143.  
  144.                     if ((error = MatchFirst(source, anchorpath)) == 0)
  145.                     {
  146.  
  147.                       do
  148.                       {
  149.                         fib = &(anchorpath->ap_Info);
  150.  
  151.                         /*
  152.                          * APF_DIDDIR indicates that we used returned from a
  153.                          * directory. In that case we clear both APF_DIDDIR and
  154.                          * APF_DODIR, so we can start afresh with the next one.
  155.                          */
  156.  
  157.  
  158.                         if (anchorpath->ap_Flags & APF_DIDDIR)
  159.                           anchorpath->ap_Flags &= ~(APF_DODIR | APF_DIDDIR);
  160.                         else
  161.                         {
  162.  
  163.                           /*
  164.                            * Make a filename for the target directory. First copy
  165.                            * targetname into buffer.
  166.                            */
  167.                           targetdir[0] = '\0';
  168.                           tmp = targetdir;
  169.                           tmp1 = target;
  170.                           while (*tmp++ = *tmp1++);
  171.  
  172.                           /* Skip sourcename in ap_Buf */
  173.                           tmp1 = sourcedir;
  174.                           tmp2 = anchorpath->ap_Buf;
  175.                           while (*tmp1++ == *tmp2++);
  176.                           /* Skip back 1 if not after a separator */
  177.                           if (*(tmp2 - 1) != '/')
  178.                             tmp2--;
  179.  
  180.                           /*
  181.                            * We hit the source itself, don't compare it, but enter
  182.                            * it.
  183.                            */
  184.                           if (*tmp2 == 0)
  185.                           {
  186.                             anchorpath->ap_Flags |= APF_DODIR;
  187.                             continue;
  188.                           }
  189.  
  190.                           /* Build it */
  191.                           if (AddPart(targetdir, tmp2, buffersize - 1))
  192.                             vargs[0] = (LONG) targetdir;
  193.                           else
  194.                           {
  195.                             PrintFault(ERROR_NO_FREE_STORE, NULL);
  196.                             break;
  197.                           }
  198.  
  199.                           /* Lock it and check it out */
  200.                           if (filelock = Lock(targetdir, SHARED_LOCK))
  201.                           {
  202.                             if ((Examine(filelock, targetfib)) == DOSTRUE)
  203.                             {
  204.                               textbuffer[0] = '\0';
  205.  
  206.                               /*
  207.                                * To get nice output without work I use AddPart() to
  208.                                * add differences to the textbuffer.
  209.                                */
  210.                               if (targetfib->fib_DirEntryType
  211.                                   != fib->fib_DirEntryType)
  212.                                 AddPart(textbuffer, "of different type", 128);
  213.                               else
  214.                               {
  215.                                 if (targetfib->fib_Size < fib->fib_Size)
  216.                                   AddPart(textbuffer, "smaller", 128);
  217.                                 else if (targetfib->fib_Size > fib->fib_Size)
  218.                                   AddPart(textbuffer, "larger", 128);
  219.  
  220.                                 if (checkdatestamp)
  221.                                 {
  222.                                   date = CompareDates((struct DateStamp *)
  223.                                         & (fib->fib_Date),
  224.                                       (struct DateStamp *) & (targetfib->fib_Date));
  225.                                   if (date < 0)
  226.                                     AddPart(textbuffer, "older", 128);
  227.                                   else if (date > 0)
  228.                                     AddPart(textbuffer, "newer", 128);
  229.                                 }
  230.                               }
  231.  
  232.  
  233.                               if (*textbuffer != NULL)
  234.                               {
  235.                                 vargs[1] = (LONG) textbuffer;
  236.                                 VFPrintf(Output(), "%s: object %s\n", vargs);
  237.                               }
  238.                             }
  239.                             else
  240.                               PrintFault(IoErr(), targetdir);
  241.                             UnLock(filelock);
  242.                           }
  243.                           else
  244.                           {
  245.                             PrintFault(IoErr(), targetdir);
  246.  
  247.                             /*
  248.                              * If and error occured on a directory name, don't enter
  249.                              * it.
  250.                              */
  251.                             if (fib->fib_DirEntryType > 0)
  252.                               continue;
  253.  
  254.                           }
  255.  
  256.                           /*
  257.                            * If the ALL keyword has been used and this is a directory
  258.                            * enter it by setting the APF_DODIR flag.
  259.                            */
  260.  
  261.                           if (fib->fib_DirEntryType > 0 && all != FALSE)
  262.                             anchorpath->ap_Flags |= APF_DODIR;
  263.  
  264.                         }
  265.  
  266.                       } while ((error = MatchNext(anchorpath)) == 0);
  267.                     }
  268.  
  269.                     MatchEnd(anchorpath);
  270.  
  271.                     if (error == ERROR_NO_MORE_ENTRIES)
  272.                       error = 0;
  273.  
  274.                     FreeMem(anchorpath, sizeof(struct AnchorPath) + buffersize);
  275.                   }
  276.                 }
  277.               }
  278.               /* Reset windowpointer */
  279.               process->pr_WindowPtr = wptr;
  280.             }
  281.             else
  282.               PrintFault(error, NULL);
  283.             FreeDosObject(DOS_FIB, targetfib);
  284.           }
  285.           FreeMem(targetdir, buffersize);
  286.         }
  287.         FreeMem(sourcedir, StrLen(sourcedir) + 129);
  288.       }
  289.       FreeArgs(readargs);
  290.     }
  291.     else
  292.       error = IoErr();
  293.  
  294.     SetIoErr(error);
  295.     if (error)
  296.     {
  297.       PrintFault(error, NULL);
  298.       if (error = ERROR_BREAK)
  299.         rc = RETURN_WARN;
  300.       else
  301.         error = RETURN_FAIL;
  302.     }
  303.     CloseLibrary((struct Library *) DOSBase);
  304.   }
  305.   return (rc);
  306. }
  307.  
  308. LONG
  309. GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize)
  310. {
  311.   UBYTE          *pathpart, *filepart;
  312.   UBYTE          *tmp1, *tmp2;
  313.   BPTR            lock;
  314.   struct FileInfoBlock *fib;
  315.   LONG            error = 0;
  316.  
  317.   /* Open own copy of dos.library if pragmas are used so it's standalone */
  318. #ifdef PRAGMAS
  319.   struct Library *DOSBase;
  320.  
  321.   if (!(DOSBase = OpenLibrary("dos.library", 36)))
  322.     return (1);
  323. #endif
  324.  
  325.   /*
  326.    * If there seems to be no path, the pathpart will point to the filepart too, so we
  327.    * need to check for that.
  328.    */
  329.   filepart = FilePart(path);
  330.   pathpart = PathPart(path);
  331.  
  332.   /*
  333.    * This also handles cases where there is only a volume/device name, only a
  334.    * directory name or a combo of those.
  335.    */
  336.   if (pathpart == path)
  337.   {
  338.  
  339.     /*
  340.      * There seems to be only one component. Copy it if it is not wild. Caller will
  341.      * have to check whether if it exists and if it is a file or directory.
  342.      */
  343.     if (!(ItsWild(pathpart)))
  344.       pathpart = NULL;
  345.   }
  346.  
  347.   if (pathpart != path)
  348.   {
  349.  
  350.     /*
  351.      * If pathpart equals filepart (pointer wise) then there is only one component
  352.      * (possible preceeded by a volume name).
  353.      */
  354.     if (pathpart == filepart)
  355.     {
  356.       if (!(ItsWild(pathpart)))
  357.         pathpart = NULL;
  358.     }
  359.     else
  360.     {
  361.       /* Try to lock it to determine if the last component is a directory. */
  362.       if (lock = Lock(path, SHARED_LOCK))
  363.       {
  364.         if (fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR))
  365.         {
  366.           if ((Examine(lock, fib)) == DOSTRUE)
  367.           {
  368.             /* Hey it's a directory after all */
  369.             if (fib->fib_DirEntryType > 0)
  370.               pathpart = NULL;
  371.           }
  372.           FreeMem(fib, sizeof(struct FileInfoBlock));
  373.         }
  374.         UnLock(lock);
  375.       }                                          /* else treat it as a filename */
  376.     }
  377.  
  378.     /* Copy the pathpart in the buffer */
  379.     tmp1 = buffer;
  380.     tmp2 = path;
  381.     while ((*tmp1++ = *tmp2++) && (tmp2 != pathpart))
  382.     {
  383.       if (tmp1 == (buffer + buffersize))
  384.       {
  385.         error = ERROR_NO_FREE_STORE;
  386.         break;
  387.       }
  388.     }
  389.     *tmp1 = '\0';                                /* NULL terminate. */
  390.   }
  391.  
  392. #ifdef PRAGMAS
  393.   CloseLibrary(DOSBase);
  394. #endif
  395.   return (error);
  396. }
  397.  
  398. UBYTE          *
  399. ItsWild(UBYTE * string)
  400. {
  401.   static UBYTE   *special = "#?*%([|";
  402.   UBYTE          *tmp = string;
  403.   COUNT           i;
  404.  
  405.   do
  406.   {
  407.     for (i = 0; special[i] != '\0'; i++)
  408.     {
  409.       if (*tmp == special[i])
  410.         return (tmp);
  411.     }
  412.     tmp++;
  413.   } while (*tmp);
  414.  
  415.   return (NULL);
  416. }
  417.  
  418. UWORD
  419. StrLen(UBYTE * string)
  420. {
  421.   UBYTE          *length = string + 1;
  422.  
  423.   while (*string++ != '\0');
  424.   return ((UWORD) (string - length));
  425. }
  426.